home *** CD-ROM | disk | FTP | other *** search
- /*
- * procRpc.c --
- *
- * Procedures to handle remote procedure calls on behalf of migrated
- * processes, and for initial setup of migrated processes.
- *
- * Copyright (C) 1986, 1988 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/proc/procRpc.c,v 9.22 92/06/15 22:29:39 jhh Exp $ SPRITE (Berkeley)";
- #endif /* not lint */
-
- #include <sprite.h>
- #include <stdlib.h>
- #include <proc.h>
- #include <procInt.h>
- #include <procMigrate.h>
- #include <mach.h>
- #include <fs.h>
- #include <migrate.h>
- #include <byte.h>
- #include <sig.h>
- #include <vm.h>
- #include <sys.h>
- #include <rpc.h>
- #include <timer.h>
- #include <sched.h>
- #include <sync.h>
- #include <sysSysCall.h>
- #include <sysSysCallParam.h>
- #include <devVid.h>
- #include <prof.h>
- #include <string.h>
- #include <stdio.h>
- #include <bstring.h>
-
- /*
- * Macro to verify that a process is migrated. If its state is MIGRATED,
- * it's okay. Otherwise, both the MIGRATING and MIGRATION_DONE flags must
- * be on. The MIGRATING flag must be on because the home process hasn't
- * finished migrating yet (hasn't context switched). The MIGRATION_DONE
- * flag must be on because otherwise we shouldn't yet be getting RPC
- * requests from the peer process.
- */
- #define IsMigrated(procPtr) \
- ((procPtr)->state == PROC_MIGRATED \
- || (((procPtr)->genFlags & (PROC_MIGRATING|PROC_MIGRATION_DONE)) \
- == (PROC_MIGRATING|PROC_MIGRATION_DONE)))
-
- /*
- * The PARANOIA code contains temporary checks to verify that
- * Proc_StringNCopy is being used correctly. -mdk 27-May-91.
- */
- #define PARANOIA 1
- #if PARANOIA
- #define IsUserAddr(x) ((x) >= mach_FirstUserAddr && (x) <= mach_LastUserAddr)
- Boolean procStringChecks = FALSE; /* do some paranoia checks on StringNCopy */
- #endif
-
- static ReturnStatus RpcProcExit _ARGS_((Proc_ControlBlock *procPtr,
- Address dataPtr, int dataLength,
- Address *replyDataPtr,
- int *replyDataLengthPtr));
- static ReturnStatus RpcProcFork _ARGS_((Proc_ControlBlock *parentProcPtr,
- Address dataPtr, int dataLength,
- Address *replyDataPtr,
- int *replyDataLengthPtr));
- static ReturnStatus RpcProcExec _ARGS_((Proc_ControlBlock *procPtr,
- Address dataPtr, int dataLength,
- Address *replyDataPtr,
- int *replyDataLengthPtr));
- static ReturnStatus RpcRemoteCall _ARGS_((Proc_RemoteCall *callPtr,
- Address dataPtr, int dataLength,
- Address *replyDataPtr,
- int *replyDataLengthPtr));
- static ReturnStatus WaitSanityChecks _ARGS_((Proc_ControlBlock *procPtr,
- int clientID));
-
- typedef ReturnStatus ((*PRS) ());
-
- /*
- * When a migrated system call is handled, a local procedure is called
- * to perform the system call. If the procedure has side effects,
- * then before the results are returned, the process state on the
- * remote node needs to be updated. (This will be the case for
- * routines such as Proc_SetIDs or Fs_Open.) The "CallBack" type
- * defines a structure containing pointers to two procedures.
- *
- * For each system call, there are several possibilities for procedures to
- * be invoked:
- *
- * 1) The call should never be migrated (or has not been implemented).
- * This is a fatal error and is identified by localPtr being "RSNIL".
- * 2) The call is a typical call that transfers data but has no side
- * effects. localPtr is set, but sideEffectsPtr is RSNIL.
- * 3) The call has side effects. localPtr and sideEffectsPtr are non-NIL.
- */
-
- typedef struct {
- PRS localPtr; /* procedure to process call locally */
- PRS sideEffectsPtr; /* procedure to update info on remote node */
- } CallBack;
-
- #define RSNIL ((PRS) NIL)
-
- static CallBack callBackVector[] = {
- /*
- * callPtr (why) sideEffectsPtr call number
- */
- { RpcProcFork, RSNIL }, /* SYS_PROC_FORK 0 */
- { RpcProcExec, RSNIL }, /* SYS_PROC_EXEC 1 */
- { RpcProcExit, RSNIL }, /* SYS_PROC_EXIT 2 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SYNC_WAITTIME 3 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_TEST_PRINTOUT 4 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_TEST_GETLINE 5 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_TEST_GETCHAR 6 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_OPEN 7 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_READ 8 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_WRITE 9 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_CLOSE 10 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_REMOVE 11 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_REMOVE_DIR 12 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_MAKE_DIR 13 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_CHANGE_DIR 14 */
- { RSNIL /* Proc_Wait */, RSNIL }, /* SYS_PROC_WAIT 15 */
- { Proc_Detach, RSNIL }, /* SYS_PROC_DETACH 16 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_GETIDS 17 */
- { Proc_SetIDs, RSNIL }, /* SYS_PROC_SETIDS 18 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_GETGROUPIDS 19 */
- { RSNIL /* Proc_SetGroupIDs */, RSNIL }, /* SYS_PROC_SETGROUPIDS 20 */
- { Proc_GetFamilyID, RSNIL }, /* SYS_PROC_GETFAMILYID 21 */
- { Proc_SetFamilyID, RSNIL }, /* SYS_PROC_SETFAMILYID 22 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_TEST_RPC 23 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_TEST_STATS 24 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_VM_CREATEVA 25 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_VM_DESTROYVA 26 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SIG_SEND 27 */
- { RSNIL /* Sig_Pause */, RSNIL }, /* SYS_SIG_PAUSE 28 */
- { RSNIL /* Sig_SetHoldMask */, RSNIL }, /* SYS_SIG_SETHOLDMASK 29 */
- { RSNIL /* Sig_SetAction */, RSNIL }, /* SYS_SIG_SETACTION 30 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROF_START 31 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROF_END 32 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROF_DUMP 33 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_VM_CMD 34 */
- { Sys_GetTimeOfDay, RSNIL }, /* SYS_SYS_GETTIMEOFDAY 35 */
- { Sys_SetTimeOfDay, RSNIL }, /* SYS_SYS_SETTIMEOFDAY 36 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SYS_DONOTHING 37 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_GETPCBINFO 38 */
- { RSNIL /* Vm_GetSegInfo */, RSNIL }, /* SYS_VM_GETSEGINFO 39 */
- { Proc_GetResUsage, RSNIL }, /* SYS_PROC_GETRESUSAGE 40 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_GETPRIORITY 41 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_SETPRIORITY 42 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_DEBUG 43 */
- { RSNIL /* Not implemented */, RSNIL }, /* SYS_PROC_PROFILE 44 */
- { RSNIL /* obsolete */, RSNIL }, /* SYS_FS_TRUNC 45 */
- { RSNIL /* obsolete */, RSNIL }, /* SYS_FS_TRUNC_ID 46 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_GET_NEW_ID 47 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_GET_ATTRIBUTES 48 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_GET_ATTR_ID 49 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_SET_ATTRIBUTES 50 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_SET_ATTR_ID 51 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_SET_DEF_PERM 52 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_IO_CONTROL 53 */
- { Dev_VidEnable, RSNIL }, /* SYS_SYS_ENABLEDISPLAY 54 */
- { RSNIL /* obsolete */, RSNIL }, /* SYS_PROC_SET_ENVIRON 55 */
- { RSNIL /* obsolete */, RSNIL }, /* SYS_PROC_UNSET_ENVIRON 56 */
- { RSNIL /* obsolete */, RSNIL }, /* SYS_PROC_GET_ENVIRON_VAR 57 */
- { RSNIL /* obsolete */, RSNIL }, /* SYS_PROC_GET_ENVIRON_RANGE 58 */
- { RSNIL /* obsolete */, RSNIL }, /* SYS_PROC_INSTALL_ENVIRON 59 */
- { RSNIL /* obsolete */, RSNIL }, /* SYS_PROC_COPY_ENVIRON 60 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SYNC_SLOWLOCK 61 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SYNC_SLOWWAIT 62 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SYNC_SLOWBROADCAST 63 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_VM_PAGESIZE 64 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_HARDLINK 65 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_RENAME 66 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_SYMLINK 67 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_READLINK 68 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_CREATEPIPE 69 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_VM_MAPKERNELINTOUSER 70 */
- { Fs_AttachDiskStub, RSNIL }, /* SYS_FS_ATTACH_DISK 71 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_SELECT 72 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SYS_SHUTDOWN 73 */
- { Proc_Migrate, RSNIL }, /* SYS_PROC_MIGRATE 74 */
- { Fs_MakeDeviceStub, RSNIL }, /* SYS_FS_MAKE_DEVICE 75 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_COMMAND 76 */
- { RSNIL /* obsolete */, RSNIL }, /* SYS_FS_LOCK 77 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_GETMACHINEINFO 78 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_NET_INSTALL_ROUTE 79 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_READVECTOR 80 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_WRITEVECTOR 81 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_CHECKACCESS 82 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_GETINTERVALTIMER 83 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_SETINTERVALTIMER 84 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_WRITEBACKID 85 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_EXEC_ENV 86 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_SET_ATTR_NEW 87 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_FS_SET_ATTR_ID_NEW 88 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_GETHOSTIDS 89 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SCHED_IDLE_PROCESSOR 90 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SCHED_START_PROCESSOR 91 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_MACH_NUM_PROCESSORS 92 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROF_PROFIL 93 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_PROC_REMOTE_EXEC 94 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_SYS_GETMACHINEINFO_NEW 95 */
- { RSNIL /* Not migrated */, RSNIL}, /* VM_MMAP 96 */
- { RSNIL /* Not migrated */, RSNIL}, /* VM_MUNMAP 97 */
- { RSNIL /* Not migrated */, RSNIL}, /* VM_MSYNC 98 */
- { RSNIL /* Not migrated */, RSNIL}, /* VM_MLOCK 99 */
- { RSNIL /* Not migrated */, RSNIL}, /* VM_MUNLOCK 100 */
- { RSNIL /* Not migrated */, RSNIL}, /* VM_MINCORE 101 */
- { RSNIL /* Not migrated */, RSNIL}, /* SYNC_SEMCTL 102 */
- { RSNIL /* Not migrated */, RSNIL}, /* SYNC_SEMGET 103 */
- { RSNIL /* Not migrated */, RSNIL}, /* SYNC_SEMOP 104 */
- { RSNIL /* Not migrated */, RSNIL}, /* VM_MPROTECT 105 */
- { RpcProcFork, RSNIL }, /* SYS_PROC_VFORK 106 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_NET_GET_ROUTES 107 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_NET_DELETE_ROUTE 108 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_ZSS_CMD 109 */
- { RSNIL /* Not migrated */, RSNIL }, /* SYS_ZEBRA_CMD 110 */
- { Sys_GetHostName, RSNIL }, /* SYS_GET_HOSTNAME 111 */
- { Sys_SetHostName, RSNIL }, /* SYS_SET_HOSTNAME 112 */
-
- };
-
-
- /*
- * Define an array of callbacks to do when handling migration commands.
- * Each of these procedures is called with the following arguments:
- *
- * func(cmdPtr, procPtr, inBufSize, inBufPtr, outBufSizePtr,
- * outBufPtrPtr)
- *
- * cmdPtr is a pointer to a ProcMigCommand structure containing the
- * processID of the process on this host, and the input and output
- * buffers are dependent on the command. The output buffer arguments
- * may be left alone, or set to point to a newly allocated buffer.
- * procPtr is generally a pointer to a locked control block for the
- * process being operated on, or is NIL in the case of
- * ProcMigAcceptMigration creating a new process.
- */
- static PRS commandCallbacks[] = {
- ProcMigAcceptMigration,
- ProcMigReceiveProcess,
- ProcMigGetUpdate,
- ProcMigEncapCallback,
- ProcMigDestroyCmd,
- ProcMigContinueProcess,
- ProcMigGetSuspend,
- };
-
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * RpcRemoteCall --
- *
- * Service a system call for a migrated process. Call the rpc
- * module to return the results, if any.
- *
- * Results:
- * Any data retured by the system call is passed back in a buffer,
- * as is its length. The result returned by the system call is
- * returned as the ReturnStatus for this procedure.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static ReturnStatus
- RpcRemoteCall(callPtr, dataPtr, dataLength, replyDataPtr,
- replyDataLengthPtr)
- Proc_RemoteCall *callPtr;
- Address dataPtr;
- int dataLength;
- Address *replyDataPtr;
- int *replyDataLengthPtr;
- {
- register Proc_ControlBlock *procPtr;
- ReturnStatus status;
- Sys_ArgArray args;
- int disp;
- int size;
- int paddedSize;
- Address inputPtr;
- Address outputPtr;
- int i;
- Proc_TraceRecord record;
-
- if (proc_MigDebugLevel > 4) {
- printf("Proc_RpcRemoteCall(%d) called.\n", callPtr->callNumber);
- }
-
- *replyDataLengthPtr = 0;
- *replyDataPtr = (Address) NIL;
-
- /*
- * It's possible for an exit to come in while a process is in the NEW
- * state if an error occurs while migrating it back home. In this case,
- * allow an exit to come in. Otherwise, be more particular about which
- * processIDs correspond to valid shadow processes.
- */
- procPtr = Proc_LockPID(callPtr->processID);
- if (procPtr == (Proc_ControlBlock *) NIL
- || ((procPtr->state != PROC_MIGRATED) &&
- !((procPtr->state == PROC_NEW) &&
- (callPtr->callNumber == SYS_PROC_EXIT)))) {
- if ((procPtr != (Proc_ControlBlock *) NIL) &&
- (procPtr->genFlags & PROC_MIGRATION_DONE)) {
- /*
- * Migration is complete, but it hasn't context switched yet.
- * This is okay, since nothing it does after that point
- * affects the process. But, if the call is EXIT, flag an error.
- */
- if (callPtr->callNumber == SYS_PROC_EXIT) {
- procPtr->genFlags |= PROC_MIG_ERROR;
- Proc_Unlock(procPtr);
- return(SUCCESS);
- }
- } else {
- printf("Warning: Proc_RpcRemoteCall: invalid pid: %x.\n",
- callPtr->processID);
- if (procPtr != (Proc_ControlBlock *) NIL) {
- printf("Proc_RpcRemoteCall: state = %d, call = %d.\n",
- (int) procPtr->state, callPtr->callNumber);
- Proc_Unlock(procPtr);
- }
- /*
- * Return a special status that indicates the migrated process
- * should be destroyed.
- */
- return (PROC_NO_PEER);
- }
- }
- Proc_Unlock(procPtr);
- if (callBackVector[callPtr->callNumber].localPtr ==
- (ReturnStatus (*) ()) NIL) {
- panic("Proc_RpcRemoteCall: can't handle call %d.\n",
- callPtr->callNumber);
- return(SYS_INVALID_SYSTEM_CALL);
- }
-
- /*
- * Set the effective process for this processor.
- */
-
- Proc_SetEffectiveProc(procPtr);
-
- if (proc_DoTrace && proc_DoCallTrace) {
- record.processID = callPtr->processID;
- record.flags = PROC_MIGTRACE_START | PROC_MIGTRACE_HOME;
- record.info.call.callNumber = callPtr->callNumber;
- Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_CALL,
- (ClientData) &record);
- }
-
- if (!callPtr->parseArgs) {
- status = (*(callBackVector[callPtr->callNumber].localPtr))
- (procPtr, dataPtr, dataLength, replyDataPtr,
- replyDataLengthPtr);
- if (proc_MigDebugLevel > 4) {
- printf("Proc_RpcRemoteCall: unparsed call %d returned %x.\n",
- callPtr->callNumber, status);
- }
-
- if (proc_DoTrace && proc_DoCallTrace) {
- record.info.call.status = status;
- record.flags &= ~PROC_MIGTRACE_START;
- Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_CALL,
- (ClientData) &record);
- }
- Proc_SetEffectiveProc((Proc_ControlBlock *) NIL);
- return(status);
- }
-
- *replyDataPtr = (Address) malloc(callPtr->replySize);
- *replyDataLengthPtr = callPtr->replySize;
- outputPtr = *replyDataPtr;
- inputPtr = dataPtr;
-
- for (i = 0; i < callPtr->numArgs; i++) {
- disp = callPtr->info[i].disposition;
- size = callPtr->info[i].size;
- paddedSize = Byte_AlignAddr(size);
- if (disp & (SYS_PARAM_ACC | SYS_PARAM_COPY)) {
- if (disp & SYS_PARAM_NIL) {
- args.argArray[i] = USER_NIL;
- } else if (disp & SYS_PARAM_OUT) {
- if (disp & SYS_PARAM_IN) {
- bcopy(inputPtr, outputPtr, size);
- inputPtr += paddedSize;
- }
- args.argArray[i] = (int) outputPtr;
- outputPtr += paddedSize;
- } else {
- args.argArray[i] = (int) inputPtr;
- inputPtr += paddedSize;
- }
- } else {
- if (size != sizeof(int)) {
- panic("Proc_RpcRemoteCall: size mismatch.\n");
- }
- args.argArray[i] = * ((int *)inputPtr);
- inputPtr += paddedSize;
- }
- }
-
- status = (*(callBackVector[callPtr->callNumber].localPtr)) (args);
- if (proc_MigDebugLevel > 4) {
- printf("Proc_RpcRemoteCall: parsed call %d returned %x.\n",
- callPtr->callNumber, status);
- }
- Proc_SetEffectiveProc((Proc_ControlBlock *) NIL);
-
- if (proc_DoTrace && proc_DoCallTrace) {
- record.info.call.status = status;
- record.flags &= ~PROC_MIGTRACE_START;
- Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_CALL,
- (ClientData) &record);
- }
-
- return(status);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * RpcProcExit --
- *
- * Perform an exit on the home node of a process.
- *
- * Results:
- * SUCCESS - the process exited successfully.
- * PROC_INVALID_PID - the process does not exist.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static ReturnStatus
- RpcProcExit(procPtr, dataPtr, dataLength, replyDataPtr,
- replyDataLengthPtr)
- register Proc_ControlBlock *procPtr;
- Address dataPtr;
- int dataLength;
- Address *replyDataPtr;
- int *replyDataLengthPtr;
- {
- Timer_Ticks kernelTicks;
- Timer_Ticks userTicks;
- int count;
- int reason; /* Why the process is dying: EXITED, SIGNALED, DESTROYED */
- int status; /* Exit status or signal # or destroy status */
- int code; /* Signal sub-status */
- Proc_PID pid;
-
- if (proc_MigDebugLevel > 4) {
- printf("RpcProcExit called.\n");
- }
-
- Proc_Lock(procPtr);
- Byte_EmptyBuffer(dataPtr, Timer_Ticks, kernelTicks);
- Timer_AddTicks(procPtr->kernelCpuUsage.ticks, kernelTicks,
- &procPtr->kernelCpuUsage.ticks);
- Byte_EmptyBuffer(dataPtr, Timer_Ticks, userTicks);
- Timer_AddTicks(procPtr->userCpuUsage.ticks, userTicks,
- &procPtr->userCpuUsage.ticks);
- #ifndef CLEAN
- /*
- * Record the remote usage for this process. Note that the usage is
- * also recorded in the total usage for this host under ProcExitProcess.
- */
- Timer_AddTicks(kernelTicks, userTicks, &userTicks);
- ProcRecordUsage(userTicks, PROC_MIG_USAGE_REMOTE_CPU);
- #endif /* CLEAN */
-
- Byte_EmptyBuffer(dataPtr, int, count);
- procPtr->numQuantumEnds += count;
- Byte_EmptyBuffer(dataPtr, int, count);
- procPtr->numWaitEvents += count;
-
- Byte_EmptyBuffer(dataPtr, int, reason);
- Byte_EmptyBuffer(dataPtr, int, status);
- Byte_EmptyBuffer(dataPtr, int, code);
-
-
- pid = procPtr->processID;
-
- /*
- * Perform an exit on behalf of the process. The process is
- * unlocked as a side effect.
- */
- ProcExitProcess(procPtr, reason, status, code, FALSE);
-
- /*
- * Remove the dependency on the other host.
- */
- ProcMigRemoveDependency(pid, TRUE);
-
- /*
- * Update statistics.
- */
- #ifndef CLEAN
- if (proc_MigDoStats) {
- PROC_MIG_DEC_STAT(remote);
- }
- #endif /* CLEAN */
-
- if (proc_MigDebugLevel > 4) {
- printf("RpcProcExit returning SUCCESS.\n");
- }
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * RpcProcExec --
- *
- * Perform an exec on the home node of a process.
- *
- * Results:
- * SUCCESS - The process is migrated and has been
- * modified.
- *
- * Side effects:
- * the process's argument string and effective userID are modified.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static ReturnStatus
- RpcProcExec(procPtr, dataPtr, dataLength, replyDataPtr,
- replyDataLengthPtr)
- register Proc_ControlBlock *procPtr;
- Address dataPtr;
- int dataLength;
- Address *replyDataPtr;
- int *replyDataLengthPtr;
- {
- int uid;
- char *argString;
-
- if (proc_MigDebugLevel > 4) {
- printf("RpcProcExec called.\n");
- }
-
- Proc_Lock(procPtr);
- Byte_EmptyBuffer(dataPtr, int, uid);
- if (uid != -1) {
- procPtr->effectiveUserID = uid;
- }
- /*
- * The data area contains the uid followed by the argString. Therefore,
- * we allocate space equal to the data length - 1. (The null terminator
- * is included in the string passed over).
- */
- argString = malloc(dataLength - 1);
- if (procPtr->argString != (char *) NIL) {
- free(procPtr->argString);
- }
- procPtr->argString = argString;
- (void) strcpy(argString, dataPtr);
-
- if (proc_MigDebugLevel > 6) {
- printf("RpcProcExec setting argString to '%s'.\n", argString);
- }
-
-
- Proc_Unlock(procPtr);
-
- if (proc_MigDebugLevel > 4) {
- printf("RpcProcExec returning SUCCESS.\n");
- }
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * RpcProcFork --
- *
- * Perform a fork on the home node of a process. This involves allocating
- * a PCB and process ID for the process, and copying certain local
- * information such as the environment.
- *
- * Results:
- * SUCCESS - the process forked successfully.
- * PROC_INVALID_PID - the process does not exist.
- *
- * Side effects:
- * A new process is created. The identifier of the newly-created
- * process is returned to the remote node in the data buffer.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static ReturnStatus
- RpcProcFork(parentProcPtr, dataPtr, dataLength, replyDataPtr,
- replyDataLengthPtr)
- register Proc_ControlBlock *parentProcPtr;
- Address dataPtr;
- int dataLength;
- Address *replyDataPtr;
- int *replyDataLengthPtr;
- {
- Proc_ControlBlock *childProcPtr; /* The new process being created */
-
- if (proc_MigDebugLevel > 3) {
- printf("RpcProcFork called.\n");
- }
- childProcPtr = ProcGetUnusedPCB();
-
- childProcPtr->Prof_Scale = 0;
- Prof_Enable(childProcPtr, parentProcPtr->Prof_Buffer,
- parentProcPtr->Prof_BufferSize, parentProcPtr->Prof_Offset,
- parentProcPtr->Prof_Scale);
-
- childProcPtr->state = PROC_MIGRATED;
- childProcPtr->genFlags |= PROC_USER | PROC_NO_VM;
- childProcPtr->syncFlags = 0;
- childProcPtr->schedFlags = 0;
- childProcPtr->exitFlags = 0;
-
- childProcPtr->billingRate = parentProcPtr->billingRate;
- childProcPtr->recentUsage = 0;
- childProcPtr->weightedUsage = 0;
- childProcPtr->unweightedUsage = 0;
-
- childProcPtr->kernelCpuUsage.ticks = timer_TicksZeroSeconds;
- childProcPtr->userCpuUsage.ticks = timer_TicksZeroSeconds;
- childProcPtr->childKernelCpuUsage.ticks = timer_TicksZeroSeconds;
- childProcPtr->childUserCpuUsage.ticks = timer_TicksZeroSeconds;
- childProcPtr->numQuantumEnds = 0;
- childProcPtr->numWaitEvents = 0;
-
- childProcPtr->parentID = parentProcPtr->processID;
- childProcPtr->userID = parentProcPtr->userID;
- childProcPtr->effectiveUserID = parentProcPtr->effectiveUserID;
- childProcPtr->familyID = parentProcPtr->familyID;
-
- if (childProcPtr->argString != (char *) NIL) {
- free(childProcPtr->argString);
- }
- if (parentProcPtr->argString != (Address) NIL) {
- childProcPtr->argString =
- (char *) malloc(strlen(parentProcPtr->argString) + 1);
- (void) strcpy(childProcPtr->argString, parentProcPtr->argString);
- } else {
- childProcPtr->argString = (char *) NIL;
- }
-
-
- Vm_ProcInit(childProcPtr);
-
- if (ProcFamilyInsert(childProcPtr, childProcPtr->familyID) != SUCCESS) {
- panic("RpcProcFork: ProcFamilyInsert failed\n");
- }
-
- /*
- * Initialize our child list to remove any old links.
- * Insert this PCB entry into the list of children of our parent.
- */
- List_Init((List_Links *) childProcPtr->childList);
- List_Insert((List_Links *) &(childProcPtr->siblingElement),
- LIST_ATREAR(parentProcPtr->childList));
-
- Sig_Fork(parentProcPtr, childProcPtr);
-
- /*
- * Initialize information for migration.
- */
-
- Byte_EmptyBuffer(dataPtr, Proc_PID, childProcPtr->peerProcessID);
- childProcPtr->peerHostID = parentProcPtr->peerHostID;
-
- /*
- * Set up the environment of the process.
- */
-
- ProcSetupEnviron(childProcPtr);
-
- /*
- * Have the new process inherit filesystem state.
- */
- Fs_InheritState(parentProcPtr, childProcPtr);
-
- /*
- * Note the dependency of the new process on the other host.
- */
- ProcMigAddDependency(childProcPtr->processID, childProcPtr->peerProcessID);
-
- /*
- * Update statistics.
- */
- #ifndef CLEAN
- if (proc_MigDoStats) {
- PROC_MIG_INC_STAT(remote);
- }
- #endif /* CLEAN */
-
- /*
- * Send back the child's process ID in the replyData buffer.
- */
-
- *replyDataLengthPtr = sizeof(Proc_PID);
- *replyDataPtr = (Address) malloc(sizeof(Proc_PID));
- * ((Proc_PID *) *replyDataPtr) = childProcPtr->processID;
-
- if (proc_MigDebugLevel > 3) {
- printf("RpcProcFork returning SUCCESS.\n");
- }
-
- Proc_Unlock(childProcPtr);
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_ByteCopy --
- *
- * Perform a copy into or out of the user's address space. If
- * the user process is migrated, copy the arguments directly and
- * let the rpc server send the results to the remote node.
- *
- * Results:
- * SUCCESS - the copy was performed successfully.
- * SYS_ARG_NOACCESS - the argument was not accessible.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Proc_ByteCopy(copyIn, numBytes, sourcePtr, destPtr)
- Boolean copyIn; /* copy into or out of kernel address space */
- int numBytes; /* The number of bytes to copy */
- Address sourcePtr; /* Where to copy from */
- Address destPtr; /* Where to copy to */
- {
- ReturnStatus status = SUCCESS;
-
- if (Proc_UseRpcBuffer()) {
- bcopy(sourcePtr, destPtr, numBytes);
- } else if (copyIn) {
- status = Vm_CopyIn(numBytes, sourcePtr, destPtr);
- } else {
- status = Vm_CopyOut(numBytes, sourcePtr, destPtr);
- }
- return(status);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_StringNCopy --
- *
- * Copy a string from the user's address space to a buffer of
- * limited length. If the user process is a ghost (an RPC that
- * was migrated home), copy the argument directly. cf.
- * Proc_ByteCopy and Vm_StringNCopy.
- *
- * Results:
- * SUCCESS
- *
- * Side effects:
- * *strNameLength is set to the actual length of the string copied.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Proc_StringNCopy(numBytes, srcStr, destStr, strLengthPtr)
- register int numBytes; /* Maximum number of bytes to copy. */
- register char *srcStr; /* String to copy. */
- register char *destStr; /* Where to copy string to. */
- int *strLengthPtr; /* Where to return actual length of
- * string copied. */
- {
- register int length;
- ReturnStatus status;
-
- if (!Proc_UseRpcBuffer()) {
- status = Vm_StringNCopy(numBytes, srcStr, destStr,
- strLengthPtr);
- } else {
- for (length = 0; (length < numBytes) && (*srcStr != '\0'); length++) {
- *destStr++ = *srcStr++;
- }
- *destStr = '\0';
- *strLengthPtr = length;
- status = SUCCESS;
- }
-
- #if PARANOIA
- /*
- * If the copy succeeded, check whether it should have. This test used
- * to come first, but then it would cause panics if someone passed in a
- * null pointer.
- */
- if (procStringChecks && status == SUCCESS) {
- if (!Proc_UseRpcBuffer() && !IsUserAddr(srcStr)) {
- panic("Proc_StringNCopy: copying from kernel address 0x%x\n",
- srcStr);
- }
- if (IsUserAddr(destStr)) {
- panic("Proc_StringNCopy: copying to user address 0x%x\n",
- destStr);
- }
- }
- #endif
-
- return status;
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_MakeStringAccessible --
- *
- * If the string is in user space, convert the user space path pointer
- * into a kernel valid pointer. If the string is in kernel space
- * already (i.e., a system call is being performed on behalf of a
- * migrated process), do nothing.
- *
- *
- * Results:
- * SYS_ARG_NOACCESS - the Vm_MakeAccessible call failed.
- * PROC_INVALID_STRING - the length of the string exceeds the maximum
- * permissible length or is not null-terminated.
- *
- * The new pointer is returned in *stringPtrPtr. The length of the
- * string is returned in *newLengthPtr if newLengthPtr is non-NIL.
- *
- * Side effects:
- * Make an area of the user code accessible.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Proc_MakeStringAccessible(maxLength, stringPtrPtr, accessLengthPtr,
- newLengthPtr)
- int maxLength; /* Maximum allowable string length */
- char **stringPtrPtr; /* On input *stringPtrPtr is a user space pointer,
- * On output *stringPtrPtr is a kernel space pointer */
- int *accessLengthPtr;/* Number of bytes actually made accessible. */
- int *newLengthPtr; /* length of the string that is made accessible */
- {
- int accessLength = maxLength;
- register int realLength;
- Boolean madeAccessible = FALSE;
- register char *charPtr;
-
- if (!Proc_UseRpcBuffer()) {
- Vm_MakeAccessible(VM_READONLY_ACCESS,
- maxLength, (Address) *stringPtrPtr,
- &accessLength, (Address *) stringPtrPtr);
- if (*stringPtrPtr == (Address)NIL) {
- return(SYS_ARG_NOACCESS);
- }
- madeAccessible = TRUE;
- *accessLengthPtr = accessLength;
- }
- /*
- * Do a length check. If the file name takes up all the addressable
- * space then it isn't null terminated and will cause problems later.
- */
- for (charPtr = *stringPtrPtr, realLength = 0;
- (realLength < accessLength) && (*charPtr != '\0');
- charPtr++, realLength++) {
- }
- if (realLength == accessLength && *charPtr != '\0') {
- if (madeAccessible) {
- Vm_MakeUnaccessible((Address) *stringPtrPtr, accessLength);
- }
- *stringPtrPtr = (Address)NIL;
- return(PROC_INVALID_STRING);
- }
- if (newLengthPtr != (int *) NIL) {
- *newLengthPtr = realLength;
- }
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_MakeUnaccessible
- *
- * If the pointer is to something that was made accessible as a
- * result of a local system call, call Vm_MakeUnaccessible.
- * Otherwise, the pointer is to a (kernel) RPC buffer and should
- * be left alone. This routine is used by generic system call
- * stubs that may be called either locally or on behalf of a
- * ghost process.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Kernel page table may be modified.
- *
- *----------------------------------------------------------------------
- */
- void
- Proc_MakeUnaccessible(addr, numBytes)
- Address addr;
- int numBytes;
- {
-
- if (!Proc_UseRpcBuffer()) {
- Vm_MakeUnaccessible(addr, numBytes);
- }
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_RpcRemoteWait --
- *
- * Perform a Proc_Wait on behalf of a migrated process.
- *
- * Results:
- * SUCCESS - an exiting/detached child was found and the information
- * about it is being returned.
- * PROC_NO_EXITS - No children have performed an exit or detach
- * (except possibly children about whom the parent has
- * already been notified).
- *
- * Side effects:
- * If the process has no exiting children and it has specified that
- * it should block until a child exits, the process is established
- * as performing a remote wait.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- ReturnStatus
- Proc_RpcRemoteWait(srvToken, clientID, command, storagePtr)
- ClientData srvToken; /* Handle on server process passed to
- * Rpc_Reply */
- int clientID; /* Sprite ID of client host */
- int command; /* Command identifier */
- Rpc_Storage *storagePtr; /* The request fields refer to the request
- * buffers and also indicate the exact amount
- * of data in the request buffers. The reply
- * fields are initialized to NIL for the
- * pointers and 0 for the lengths. This can
- * be passed to Rpc_Reply */
- {
- ReturnStatus status;
- ProcChildInfo *childInfoPtr;
- register ProcRemoteWaitCmd *cmdPtr;
- Proc_PID *pidArray;
- Rpc_ReplyMem *replyMemPtr;
- Proc_ControlBlock *procPtr;
-
- if (proc_MigDebugLevel > 3) {
- printf("Proc_RpcRemoteWait entered.\n");
-
- }
-
- cmdPtr = (ProcRemoteWaitCmd *) storagePtr->requestParamPtr;
- procPtr = Proc_LockPID(cmdPtr->pid);
-
- if (procPtr == (Proc_ControlBlock *) NIL) {
- if (proc_MigDebugLevel > 1) {
- printf("Proc_RpcRemoteWait: no such process %x\n", cmdPtr->pid);
- }
- return (PROC_NO_PEER);
- } else {
- status = WaitSanityChecks(procPtr, clientID);
- if (status != SUCCESS) {
- Proc_Unlock(procPtr);
- return (status);
- }
- }
-
- /*
- * If the local process is still finishing up migration, wait for it to
- * complete.
- */
- if (procPtr->state != PROC_MIGRATED) {
- if (proc_MigDebugLevel > 2) {
- printf("%s: waiting for process %x to context switch.\n",
- "Proc_RpcRemoteWait", procPtr->processID);
- }
- Proc_Unlock(procPtr);
- status = Proc_WaitForMigration(cmdPtr->pid);
- if (status != SUCCESS) {
- if (proc_MigDebugLevel > 1) {
- printf("%s: error waiting for pid %x to context switch.\n",
- "Proc_RpcRemoteWait", cmdPtr->pid);
- }
- return (PROC_NO_PEER);
- }
- Proc_Lock(procPtr);
- status = WaitSanityChecks(procPtr, clientID);
- if (status != SUCCESS) {
- if (proc_MigDebugLevel > 1) {
- printf("%s: error after waiting for pid %x to ctxt switch\n",
- "Proc_RpcRemoteWait", procPtr->processID);
- }
- Proc_Unlock(procPtr);
- return (status);
- }
- }
-
- pidArray = (Proc_PID *) storagePtr->requestDataPtr;
- childInfoPtr = (ProcChildInfo *) malloc(sizeof(ProcChildInfo));
-
- status = ProcServiceRemoteWait(procPtr, cmdPtr->flags, cmdPtr->numPids,
- pidArray, cmdPtr->token,
- childInfoPtr);
-
- Proc_Unlock(procPtr);
- if (status == SUCCESS) {
- storagePtr->replyDataPtr = (Address) childInfoPtr;
- storagePtr->replyDataSize = sizeof(ProcChildInfo);
- replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
- replyMemPtr->paramPtr = (Address) NIL;
- replyMemPtr->dataPtr = storagePtr->replyDataPtr;
-
- Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
- (ClientData) replyMemPtr);
- } else {
- free((Address) childInfoPtr);
- }
-
- if (proc_MigDebugLevel > 3) {
- printf("Proc_RpcRemoteWait: returning %x.\n", status);
- }
- return(status);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * WaitSanityChecks --
- *
- * Do some sanity checks for the remote wait() call on the given
- * locked PCB.
- *
- * Results:
- * Returns a Sprite status code.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static ReturnStatus
- WaitSanityChecks(procPtr, clientID)
- Proc_ControlBlock *procPtr;
- int clientID; /* host that made the wait request */
- {
- /*
- * Verify that the process is migrated and that the process's remote
- * host is the one making the wait request.
- */
- if (!IsMigrated(procPtr) || procPtr->peerHostID != clientID) {
- if (proc_MigDebugLevel > 1) {
- if (procPtr->peerHostID != clientID) {
- printf("%s: process %x has peer host %d, expected %d.\n",
- "Proc_RpcRemoteWait", procPtr->processID,
- procPtr->peerHostID, clientID);
- } else {
- printf("%s: process %x not migrated (state %d, flags 0x%x)\n",
- "Proc_RpcRemoteWait", procPtr->processID,
- procPtr->state, procPtr->genFlags);
- }
- }
- return(PROC_NO_PEER);
- }
-
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_RpcMigCommand --
- *
- * Handle a request regarding process migration. This may be a
- * request to initiate migration, a buffer containing part or all
- * of the encapsulated state of a process, a callback by another
- * module during state transfer, or a command to asynchronously
- * kill a migrated process due to some error.
- *
- * Results:
- * SUCCESS is returned to the rpc daemon invoking this procedure.
- * Various ReturnStatus values may be returned via the RPC itself.
- * It is either SUCCESS or some error returned by a lower level routine
- * (e.g., no such process). In addition, the called routine may
- * return arbitrary data.
- *
- * Side effects:
- * Variable (see above).
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- Proc_RpcMigCommand(srvToken, hostID, command, storagePtr)
- ClientData srvToken; /* Handle on server process passed to
- * Rpc_Reply */
- int hostID; /* Sprite ID of host invoking RPC */
- int command; /* Command identifier */
- Rpc_Storage *storagePtr; /* The request fields refer to the request
- * buffers and also indicate the exact amount
- * of data in the request buffers. The reply
- * fields are initialized to NIL for the
- * pointers and 0 for the lengths. This can
- * be passed to Rpc_Reply */
- {
- ReturnStatus status;
- Rpc_ReplyMem *replyMemPtr;
- ProcMigCmd *commandPtr =
- (ProcMigCmd *) storagePtr->requestParamPtr;
- Proc_MigBuffer inBuf;
- Proc_MigBuffer outBuf;
- Proc_ControlBlock *procPtr;
- int requestSize;
-
- if (proc_MigDebugLevel > 5) {
- printf("Proc_RpcMigCommand: called from host %d with command %d commandPtr %x.\n",
- hostID, command, (int) commandPtr);
- }
- if (storagePtr->requestParamSize != sizeof(ProcMigCmd)) {
- if (proc_MigDebugLevel > 0) {
- printf("Proc_RpcMigCommand: called from host %d with invalid input buffer size (%d instead of %d).\n",
- hostID, storagePtr->requestParamSize, sizeof(ProcMigCmd));
- }
- status = GEN_INVALID_ARG;
- goto done;
- }
-
- if (commandPtr->remotePid != (Proc_PID) NIL) {
- PROC_GET_VALID_PCB(commandPtr->remotePid, procPtr);
- if (procPtr == (Proc_ControlBlock *) NIL) {
- if (proc_MigDebugLevel > 3) {
- panic("Proc_RpcMigCommand: Invalid pid: %x.\n", commandPtr->remotePid);
- }
- if (proc_MigDebugLevel > 1) {
- printf("Proc_RpcMigCommand: Invalid pid: %x.\n",
- commandPtr->remotePid);
- }
- status = PROC_NO_PEER;
- goto done;
- }
- } else {
- procPtr = (Proc_ControlBlock *) NIL;
- }
-
- if (commandPtr->command >= PROC_MIGRATE_CMD_NUM_TYPES ||
- commandPtr->command < 0) {
- if (proc_MigDebugLevel > 0) {
- printf("Proc_RpcMigCommand: invalid command number: %d.\n",
- commandPtr->command);
- }
- status = GEN_INVALID_ARG;
- goto done;
- }
- requestSize = storagePtr->requestDataSize;
- /*
- * Normally we just pass the buffer as it's given to us, but
- * it might be a piece of a larger buffer that we malloc and free.
- * In that case, do some sanity checking and then copy in the buffer.
- */
- if (commandPtr->totalSize == requestSize) {
- inBuf.size = requestSize;
- inBuf.ptr = storagePtr->requestDataPtr;
- } else {
- if (procPtr == (Proc_ControlBlock *) NIL) {
- if (proc_MigDebugLevel > 0) {
- printf("Proc_RpcMigCommand: partial buffer not allowed before process set up.\n");
- status = PROC_NO_PEER;
- goto done;
- }
- }
- if (commandPtr->offset == 0) {
- if (procPtr->migCmdBuffer != (Address) NIL) {
- if (proc_MigDebugLevel > 0) {
- printf("Proc_RpcMigCommand: buffer already established for process %x.\n",
- procPtr->processID);
- }
- free(procPtr->migCmdBuffer);
- }
- procPtr->migCmdBuffer = malloc(commandPtr->totalSize);
- procPtr->migCmdBufSize = commandPtr->totalSize;
- } else {
- if (procPtr->migCmdBuffer == (Address) NIL) {
- if (proc_MigDebugLevel > 0) {
- printf("Proc_RpcMigCommand: no buffer established for process %x.\n",
- procPtr->processID);
- }
- status = GEN_INVALID_ARG;
- goto done;
- }
- if (commandPtr->totalSize != procPtr->migCmdBufSize ||
- commandPtr->offset + requestSize > commandPtr->totalSize) {
- if (proc_MigDebugLevel > 0) {
- printf("Proc_RpcMigCommand: mismatch in buffer size for process %x.\n",
- procPtr->processID);
- }
- status = GEN_INVALID_ARG;
- goto done;
- }
- }
- bcopy(storagePtr->requestDataPtr,
- procPtr->migCmdBuffer + commandPtr->offset,
- requestSize);
- if (commandPtr->offset + requestSize < commandPtr->totalSize) {
- status = SUCCESS;
- goto done;
- }
- inBuf.size = commandPtr->totalSize;
- inBuf.ptr = procPtr->migCmdBuffer;
- }
-
- outBuf.size = 0;
- outBuf.ptr = (Address) NIL;
-
- status = (*commandCallbacks[commandPtr->command])
- (commandPtr, procPtr, &inBuf, &outBuf);
- #ifdef lint
- status = ProcMigAcceptMigration(commandPtr, procPtr, &inBuf, &outBuf);
- status = ProcMigReceiveProcess(commandPtr, procPtr, &inBuf, &outBuf);
- status = ProcMigUpdateState(commandPtr, procPtr, &inBuf, &outBuf);
- status = ProcMigEncapCallback(commandPtr, procPtr, &inBuf, &outBuf);
- status = ProcMigDestroyCmd(commandPtr, procPtr, &inBuf, &outBuf);
- #endif /* lint */
- /*
- * Free the malloc'ed buffer if it exists.
- */
- if ((procPtr != (Proc_ControlBlock *) NIL) &&
- (procPtr->migCmdBuffer != (Address) NIL)) {
- free(procPtr->migCmdBuffer);
- procPtr->migCmdBuffer = (Address) NIL;
- }
- if (status == SUCCESS && outBuf.size > 0) {
- storagePtr->replyDataPtr = outBuf.ptr;
- storagePtr->replyDataSize = outBuf.size;
-
- replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
- replyMemPtr->paramPtr = (Address) NIL;
- replyMemPtr->dataPtr = outBuf.ptr;
- if (proc_MigDebugLevel > 5) {
- printf("Proc_RpcMigCommand: returning status %x.\n", status);
- }
- Rpc_Reply(srvToken, SUCCESS, storagePtr, Rpc_FreeMem,
- (ClientData) replyMemPtr);
- } else {
- done:
- if (proc_MigDebugLevel > 2) {
- printf("Proc_RpcMigCommand: returning status %x.\n", status);
- }
- Rpc_Reply(srvToken, status,
- storagePtr, (int(*)()) NIL, (ClientData) NIL);
- }
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Proc_RpcRemoteCall --
- *
- * Handle a system call for a migrated process.
- *
- * Note: now that this has been moved into the proc module, it
- * can be collapsed into the routine it calls....
- *
- * Results:
- * A return status.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- /*ARGSUSED*/
- ReturnStatus
- Proc_RpcRemoteCall(srvToken, clientID, command, storagePtr)
- ClientData srvToken; /* Handle on server process passed to
- * Rpc_Reply */
- int clientID; /* Sprite ID of client host */
- int command; /* Command identifier */
- Rpc_Storage *storagePtr; /* The request fields refer to the request
- * buffers and also indicate the exact amount
- * of data in the request buffers. The reply
- * fields are initialized to NIL for the
- * pointers and 0 for the lengths. This can
- * be passed to Rpc_Reply */
- {
- Rpc_ReplyMem *replyMemPtr;
- Address returnData = (Address) NIL;
- int returnDataLength = 0;
- ReturnStatus status;
-
- status = RpcRemoteCall((Proc_RemoteCall *)storagePtr->requestParamPtr,
- storagePtr->requestDataPtr, storagePtr->requestDataSize,
- &returnData, &returnDataLength);
-
- storagePtr->replyDataPtr = returnData;
- storagePtr->replyDataSize = returnDataLength;
-
- replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
- replyMemPtr->paramPtr = (Address) NIL;
- replyMemPtr->dataPtr = returnData;
- Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
- (ClientData) replyMemPtr);
-
- return(status);
- }
-